package com.dou.sample.opengl_project.utls;

import static android.opengl.GLES20.GL_COMPILE_STATUS;
import static android.opengl.GLES20.GL_FRAGMENT_SHADER;
import static android.opengl.GLES20.GL_LINK_STATUS;
import static android.opengl.GLES20.GL_VALIDATE_STATUS;
import static android.opengl.GLES20.GL_VERTEX_SHADER;
import static android.opengl.GLES20.glAttachShader;
import static android.opengl.GLES20.glCompileShader;
import static android.opengl.GLES20.glCreateProgram;
import static android.opengl.GLES20.glCreateShader;
import static android.opengl.GLES20.glDeleteShader;
import static android.opengl.GLES20.glGetProgramiv;
import static android.opengl.GLES20.glGetShaderiv;
import static android.opengl.GLES20.glLinkProgram;
import static android.opengl.GLES20.glShaderSource;
import static android.opengl.GLES20.glValidateProgram;

/**
 * Created by Dou on 2018/1/15.
 */

public class ShaderHelper {
    private static final String TAG = ShaderHelper.class.getSimpleName();

    public static int compileVertexShader(String shaderCode){
        return compileShader(GL_VERTEX_SHADER, shaderCode);
    }

    public static int compileFragmentShader(String shaderCode){
        return compileShader(GL_FRAGMENT_SHADER, shaderCode);
    }

    private static int compileShader(int type, String shaderCode) {
        int shaderObjectId = glCreateShader(type);

        if (shaderObjectId == 0){
            return 0;
        }

        glShaderSource(shaderObjectId,  shaderCode);
        glCompileShader(shaderObjectId);
        int[] comileState = new int[1];
        glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, comileState,0);

        if (comileState[0] == 0){
            glDeleteShader(shaderObjectId);
            return 0;
        }

        return shaderObjectId;
    }

    public static int linkProgram(int vertexShaderId, int fragmentShaderId){
        int programObjectId = glCreateProgram();

        if (programObjectId == 0){
            return 0;
        }

        glAttachShader(programObjectId, vertexShaderId);
        glAttachShader(programObjectId, fragmentShaderId);

        glLinkProgram(programObjectId);
        int[] linkState = new int[1];
        glGetProgramiv(programObjectId, GL_LINK_STATUS, linkState, 0);

        if (linkState[0] == 0){
            return 0;
        }

        return programObjectId;
    }

    public boolean validateProgram(int programId){
        glValidateProgram(programId);

        int[] validateState = new int[1];
        glGetProgramiv(programId, GL_VALIDATE_STATUS, validateState,0);
        if (validateState[0] == 0){
            return false;
        } else {
            return true;
        }
    }

    public static int buildProgram(String vertexShaderCode, String fragmentShaderCode){
        int program;

        int vertexShader = compileVertexShader(vertexShaderCode);
        int fragmentShader = compileFragmentShader(fragmentShaderCode);

        program = linkProgram(vertexShader, fragmentShader);

        return program;
    }
}
